home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / demos / OpenGL / stonehenge / Stone.c++ < prev    next >
C/C++ Source or Header  |  1996-11-11  |  20KB  |  817 lines

  1. /*
  2.  * (c) Copyright 1993, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software for
  6.  * any purpose and without fee is hereby granted, provided that the above
  7.  * copyright notice appear in all copies and that both the copyright notice
  8.  * and this permission notice appear in supporting documentation, and that
  9.  * the name of Silicon Graphics, Inc. not be used in advertising
  10.  * or publicity pertaining to distribution of the software without specific,
  11.  * written prior permission.
  12.  *
  13.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  14.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  15.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  16.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  17.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  18.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  19.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  20.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  21.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  22.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  23.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  24.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  25.  *
  26.  * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND
  27.  * Use, duplication, or disclosure by the Government is subject to
  28.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  29.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  30.  * clause at DFARS 252.227-7013 and/or in similar or successor
  31.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  32.  * Unpublished-- rights reserved under the copyright laws of the
  33.  * United States.  Contractor/manufacturer is Silicon Graphics,
  34.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  35.  *
  36.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  37.  */
  38. #include <GL/glu.h>
  39. #include <GL/glx.h>
  40.  
  41. #include <math.h>
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44.  
  45. #include "Stone.h"
  46.  
  47. const GLfloat root2 = 1.4142136;
  48. const GLfloat root3 = sqrt(3.);
  49. const GLfloat rt_half = .70710678;
  50.  
  51. inline float radians(float a) {return M_PI * a / 180.0; }
  52.  
  53. inline float sign(float a) {return (a > 0. ? 1 : (a < 0. ? -1 : 0)); }
  54.  
  55. Stone::Stone() 
  56. {
  57.   translation.set(0, 0, 0);
  58.   rotation = 0;
  59.   dimensions.set(1, 1, 1);
  60.  
  61.   erosion = 0;
  62.  
  63.   points_valid = transforms_valid = 0;
  64. }
  65.  
  66. Stone::~Stone() 
  67. {
  68. }
  69.  
  70. Stone Stone::operator=(Stone a)
  71. {
  72.   int i;
  73.  
  74.   translation = a.translation;
  75.   rotation = a.rotation;
  76.   dimensions = a.dimensions;
  77.  
  78.   erosion = a.erosion;
  79.  
  80.   if (a.points_valid && a.transforms_valid) {
  81.     for (i = 0; i < 24; i++) points[i] = a.points[i];
  82.     points_valid = transforms_valid = 1;
  83.   } else points_valid = transforms_valid = 0;
  84.  
  85.   return *this;
  86. }
  87.  
  88. void Stone::set_dimensions(GLfloat x, GLfloat y, GLfloat z)
  89. {
  90.   dimensions.set(x, y, z);
  91.   points_valid = 0;
  92. }
  93.  
  94. void Stone::set_dimensions(Point p)
  95. {
  96.   dimensions = p;
  97.   points_valid = 0;
  98. }
  99.  
  100. void Stone::erode(float p)
  101. {
  102.   erosion += p;
  103.   points_valid = 0;
  104. }
  105.  
  106. void Stone::translate(GLfloat x, GLfloat y, GLfloat z)
  107. {
  108.   translation.pt[0] += x;
  109.   translation.pt[1] += y;
  110.   translation.pt[2] += z;
  111.   points_valid = 0;
  112. }
  113.  
  114. void Stone::translate(Point p)
  115. {
  116.   translation += p;
  117.   points_valid = 0;
  118. }
  119.  
  120. void Stone::rotate_self_aboutz(GLfloat angle)
  121. {
  122.   rotation += angle;
  123.   points_valid = 0;
  124. }
  125.  
  126. void Stone::draw()
  127. {
  128.   compute_points();
  129.  
  130.   glPushMatrix();
  131.   glRotatef(rotation, 0, 0, 1);
  132.   glTranslatef(translation.pt[0], translation.pt[1], translation.pt[2]);
  133.   glScalef(dimensions.pt[0], dimensions.pt[1], dimensions.pt[2]);
  134.  
  135.   draw_faces();
  136.   draw_edges();
  137.   draw_corners();
  138.  
  139.   glPopMatrix();
  140. }
  141.  
  142. void Stone::compute_points()
  143. {
  144.   GLfloat e = 1.0 - erosion;
  145.  
  146.   if (points_valid) return;
  147.  
  148.   points[0].set(1, e, e);
  149.   points[1].set(e, 1, e);
  150.   points[2].set(e, e, 1);
  151.  
  152.   points[3].set(-e, e, 1);
  153.   points[4].set(-e, 1, e);
  154.   points[5].set(-1, e, e);
  155.  
  156.   points[6].set(e, -e, 1);
  157.   points[7].set(e, -1, e);
  158.   points[8].set(1, -e, e);
  159.  
  160.   points[9 ].set(e, e, -1);
  161.   points[10].set(e, 1, -e);
  162.   points[11].set(1, e, -e);
  163.  
  164.   points[12].set(-1, -e, e);
  165.   points[13].set(-e, -1, e);
  166.   points[14].set(-e, -e, 1);
  167.  
  168.   points[15].set(1, -e, -e);
  169.   points[16].set(e, -1, -e);
  170.   points[17].set(e, -e, -1);
  171.  
  172.   points[18].set(-1, e, -e);
  173.   points[19].set(-e, 1, -e);
  174.   points[20].set(-e, e, -1);
  175.   
  176.   points[21].set(-e, -e, -1);
  177.   points[22].set(-e, -1, -e);
  178.   points[23].set(-1, -e, -e);
  179.  
  180.   points_valid = 1;
  181.   transforms_valid = 0;
  182. }
  183.  
  184. inline Point Stone::trans_rot_point(Point p, float c, float s)
  185. {
  186.   Point val;
  187.   val = p + translation;
  188.   val = val.rotate_aboutz(c, s);
  189.   return val;
  190. }
  191.  
  192. inline Point Stone::transform_point(Point p, float c, float s)
  193. {
  194.   Point val;
  195.   val = p.scale(dimensions);
  196.   val += translation;
  197.   val = val.rotate_aboutz(c, s);
  198.   return val;
  199. }
  200.  
  201. void Stone::transform_points()
  202. {
  203.   float c, s;
  204.   int i;
  205.  
  206.   if (points_valid && transforms_valid) return;
  207.   points_valid = 0;
  208.   compute_points();
  209.  
  210.   c = cos(radians(rotation));
  211.   s = sin(radians(rotation));
  212.  
  213.   for (i = 0; i < 24; i++) points[i] = transform_point(points[i], c, s);
  214.  
  215.   points_valid = 0;
  216.   transforms_valid = 1;
  217. }    
  218.  
  219. void Stone::draw_faces(int flat)
  220. {
  221.   draw_faces(points, flat);
  222. }
  223.  
  224. void Stone::draw_faces(Point *p, int flat)
  225. {
  226.   glBegin(GL_QUADS);
  227.  
  228.   glNormal3f(1, 0, 0);
  229.   if (flat) glTexCoord2fv(p[15].pt);
  230.   else glTexCoord2f(0, 0);
  231.   glVertex3fv(p[15].pt);
  232.   if (flat) glTexCoord2fv(p[11].pt);
  233.   else glTexCoord2f(1, 0);
  234.   glVertex3fv(p[11].pt);
  235.   if (flat) glTexCoord2fv(p[0].pt);
  236.   else glTexCoord2f(1, 1);
  237.   glVertex3fv(p[0].pt);
  238.   if (flat) glTexCoord2fv(p[8].pt);
  239.   else glTexCoord2f(0, 1);
  240.   glVertex3fv(p[8].pt);
  241.  
  242.   glNormal3f(-1, 0, 0);
  243.   if (flat) glTexCoord2fv(p[12].pt);
  244.   else glTexCoord2f(0, 0);
  245.   glVertex3fv(p[12].pt);
  246.   if (flat) glTexCoord2fv(p[5].pt);
  247.   else glTexCoord2f(1, 0);
  248.   glVertex3fv(p[5].pt);
  249.   if (flat) glTexCoord2fv(p[18].pt);
  250.   else glTexCoord2f(1, 1);
  251.   glVertex3fv(p[18].pt);
  252.   if (flat) glTexCoord2fv(p[23].pt);
  253.   else glTexCoord2f(0, 1);
  254.   glVertex3fv(p[23].pt);
  255.  
  256.   glNormal3f(0, 1, 0);
  257.   if (flat) glTexCoord2fv(p[4].pt);
  258.   else glTexCoord2f(0, 0);
  259.   glVertex3fv(p[4].pt);
  260.   if (flat) glTexCoord2fv(p[1].pt);
  261.   else glTexCoord2f(1, 0);
  262.   glVertex3fv(p[1].pt);
  263.   if (flat) glTexCoord2fv(p[10].pt);
  264.   else glTexCoord2f(1, 1);
  265.   glVertex3fv(p[10].pt);
  266.   if (flat) glTexCoord2fv(p[19].pt);
  267.   else glTexCoord2f(0, 1);
  268.   glVertex3fv(p[19].pt);
  269.   
  270.   glNormal3f(0, -1, 0);
  271.   if (flat) glTexCoord2fv(p[22].pt);
  272.   else glTexCoord2f(0, 0);
  273.   glVertex3fv(p[22].pt);
  274.   if (flat) glTexCoord2fv(p[16].pt);
  275.   else glTexCoord2f(1, 0);
  276.   glVertex3fv(p[16].pt);
  277.   if (flat) glTexCoord2fv(p[7].pt);
  278.   else glTexCoord2f(1, 1);
  279.   glVertex3fv(p[7].pt);
  280.   if (flat) glTexCoord2fv(p[13].pt);
  281.   else glTexCoord2f(0, 1);
  282.   glVertex3fv(p[13].pt);
  283.  
  284.   glNormal3f(0, 0, 1);
  285.   if (flat) glTexCoord2fv(p[14].pt);
  286.   else glTexCoord2f(0, 0);
  287.   glVertex3fv(p[14].pt);
  288.   if (flat) glTexCoord2fv(p[6].pt); 
  289.   else glTexCoord2f(1, 0);
  290.   glVertex3fv(p[6].pt);
  291.   if (flat) glTexCoord2fv(p[2].pt);
  292.   else glTexCoord2f(1, 1);
  293.   glVertex3fv(p[2].pt);
  294.   if (flat) glTexCoord2fv(p[3].pt);
  295.   else glTexCoord2f(0, 1);
  296.   glVertex3fv(p[3].pt);
  297.  
  298.   glNormal3f(0, 0, -1);
  299.   if (flat) glTexCoord2fv(p[20].pt);
  300.   else glTexCoord2f(0, 0);
  301.   glVertex3fv(p[20].pt);
  302.   if (flat) glTexCoord2fv(p[9].pt);
  303.   else glTexCoord2f(1, 0);
  304.   glVertex3fv(p[9].pt);
  305.   if (flat) glTexCoord2fv(p[17].pt);
  306.   else glTexCoord2f(1, 1);
  307.   glVertex3fv(p[17].pt);
  308.   if (flat) glTexCoord2fv(p[21].pt);
  309.   else glTexCoord2f(0, 1);
  310.   glVertex3fv(p[21].pt);
  311.  
  312.   glEnd();
  313. }
  314.  
  315. void Stone::draw_edges(int flat)
  316. {
  317.   draw_edges(points, flat);
  318. }
  319.  
  320. void Stone::draw_edges(Point *p, int flat)
  321. {
  322.   Point n1, n2;
  323.  
  324.   glBegin(GL_QUADS);
  325.  
  326.   n1.set(0, 1, 0);
  327.   n2.set(1, 0, 0);
  328.   draw_edge(n1, n2, p, 10, 1, 0, 11, flat);
  329.  
  330.   n1.set(1, 0, 0);
  331.   n2.set(0, -1, 0);
  332.   draw_edge(n1, n2, p, 15, 8, 7, 16, flat);
  333.  
  334.   n1.set(1, 0, 0);
  335.   n2.set(0, 0, 1);
  336.   draw_edge(n1, n2, p, 8, 0, 2, 6, flat);
  337.  
  338.   n1.set(1, 0, 0);
  339.   n2.set(0, 0, -1);
  340.   draw_edge(n1, n2, p, 11, 15, 17, 9, flat);
  341.  
  342.   n1.set(0, 1, 0);
  343.   n2.set(-1, 0, 0);
  344.   draw_edge(n1, n2, p, 4, 19, 18, 5, flat);
  345.  
  346.   n1.set(-1, 0, 0);
  347.   n2.set(0, -1, 0);
  348.   draw_edge(n1, n2, p, 12, 23, 22, 13, flat);
  349.   
  350.   n1.set(-1, 0, 0);
  351.   n2.set(0, 0, 1);
  352.   draw_edge(n1, n2, p, 5, 12, 14, 3, flat);
  353.  
  354.   n2.set(-1, 0, 0);
  355.   n1.set(0, 0, -1);
  356.   draw_edge(n1, n2, p, 20, 21, 23, 18, flat);
  357.     
  358.   n1.set(0, 1, 0);
  359.   n2.set(0, 0, 1);
  360.   draw_edge(n1, n2, p, 1, 4, 3, 2, flat);
  361.  
  362.   n1.set(0, 1, 0);
  363.   n2.set(0, 0, -1);
  364.   draw_edge(n1, n2, p, 19, 10, 9, 20, flat);
  365.  
  366.   n1.set(0, -1, 0);
  367.   n2.set(0, 0, 1);
  368.   draw_edge(n1, n2, p, 13, 7, 6, 14, flat);
  369.  
  370.   n1.set(0, -1, 0);
  371.   n2.set(0, 0, -1); 
  372.   draw_edge(n1, n2, p, 16, 22, 21, 17, flat);
  373.  
  374.   glEnd();
  375. }
  376.  
  377. void Stone::draw_edge(Point n1, Point n2, Point *p, 
  378.               int a, int b, int c, int d, int flat)
  379. {
  380.   glNormal3fv(n1.pt);
  381.   if (flat) glTexCoord2fv(p[a].pt);
  382.   else glTexCoord2f(0, 0);
  383.   glVertex3fv(p[a].pt);
  384.   if (flat) glTexCoord2fv(p[b].pt);
  385.   else glTexCoord2f(0, 1);
  386.   glVertex3fv(p[b].pt);
  387.   glNormal3fv(n2.pt);
  388.   if (flat) glTexCoord2fv(p[c].pt);
  389.   else glTexCoord2f(1, 1);
  390.   glVertex3fv(p[c].pt);
  391.   if (flat) glTexCoord2fv(p[d].pt);
  392.   else glTexCoord2f(1, 0);
  393.   glVertex3fv(p[d].pt);
  394. }
  395.  
  396. void Stone::draw_corners(Point *p, int flat)
  397. {
  398.   GLfloat e = 1.0 - erosion;
  399.  
  400.   glBegin(GL_TRIANGLES);
  401.  
  402.   if (flat) glTexCoord2fv(p[0].pt);
  403.   else glTexCoord2f(0, 0);
  404.   glNormal3f(1, 0, 0);
  405.   glVertex3fv(p[0].pt);
  406.   if (flat) glTexCoord2fv(p[1].pt);
  407.   else glTexCoord2f(1, 0);
  408.   glNormal3f(0, 1, 0);
  409.   glVertex3fv(p[1].pt);
  410.   if (flat) glTexCoord2fv(p[2].pt);
  411.   else glTexCoord2f(.5, 1);
  412.   glNormal3f(0, 0, 1);
  413.   glVertex3fv(p[2].pt);
  414.  
  415.   if (flat) glTexCoord2fv(p[3].pt); 
  416.   else glTexCoord2f(0, 0);
  417.   glNormal3f(0, 0, 1);
  418.   glVertex3fv(p[3].pt);
  419.   if (flat) glTexCoord2fv(p[4].pt); 
  420.   else glTexCoord2f(1, 0);
  421.   glNormal3f(0, 1, 0);
  422.   glVertex3fv(p[4].pt);
  423.   if (flat) glTexCoord2fv(p[5].pt); 
  424.   else glTexCoord2f(.5, 1);
  425.   glNormal3f(-1, 0, 0);
  426.   glVertex3fv(p[5].pt);
  427.  
  428.   if (flat) glTexCoord2fv(p[6].pt); 
  429.   else glTexCoord2f(0, 0);
  430.   glNormal3f(0, 0, 1);
  431.   glVertex3fv(p[6].pt);
  432.   if (flat) glTexCoord2fv(p[7].pt); 
  433.   else glTexCoord2f(1, 0);
  434.   glNormal3f(0, -1, 0);
  435.   glVertex3fv(p[7].pt);
  436.   if (flat) glTexCoord2fv(p[8].pt); 
  437.   else glTexCoord2f(.5, 1);
  438.   glNormal3f(1, 0, 0);
  439.   glVertex3fv(p[8].pt);
  440.  
  441.   if (flat) glTexCoord2fv(p[9].pt); 
  442.   else glTexCoord2f(0, 0);
  443.   glNormal3f(0, 0, -1);
  444.   glVertex3fv(p[9].pt);
  445.   if (flat) glTexCoord2fv(p[10].pt); 
  446.   else glTexCoord2f(1, 0);
  447.   glNormal3f(0, 1, 0);
  448.   glVertex3fv(p[10].pt);
  449.   if (flat) glTexCoord2fv(p[11].pt); 
  450.   else glTexCoord2f(.5, 1);
  451.   glNormal3f(1, 0, 0);
  452.   glVertex3fv(p[11].pt);
  453.  
  454.   if (flat) glTexCoord2fv(p[12].pt); 
  455.   else glTexCoord2f(0, 0);
  456.   glNormal3f(-1, 0, 0);
  457.   glVertex3fv(p[12].pt);
  458.   if (flat) glTexCoord2fv(p[13].pt); 
  459.   else glTexCoord2f(1, 0);
  460.   glNormal3f(0, -1, 0);
  461.   glVertex3fv(p[13].pt);
  462.   if (flat) glTexCoord2fv(p[14].pt); 
  463.   else glTexCoord2f(.5, 1);
  464.   glNormal3f(0, 0, 1);
  465.   glVertex3fv(p[14].pt);
  466.  
  467.   if (flat) glTexCoord2fv(p[15].pt); 
  468.   else glTexCoord2f(0, 0);
  469.   glNormal3f(1, 0, 0);
  470.   glVertex3fv(p[15].pt);
  471.   if (flat) glTexCoord2fv(p[16].pt); 
  472.   else glTexCoord2f(1, 0);
  473.   glNormal3f(0, -1, 0);
  474.   glVertex3fv(p[16].pt);
  475.   if (flat) glTexCoord2fv(p[17].pt); 
  476.   else glTexCoord2f(.5, 1);
  477.   glNormal3f(0, 0, -1);
  478.   glVertex3fv(p[17].pt);
  479.  
  480.   if (flat) glTexCoord2fv(p[18].pt); 
  481.   else glTexCoord2f(0, 0);
  482.   glNormal3f(-1, 0, 0);
  483.   glVertex3fv(p[18].pt);
  484.   if (flat) glTexCoord2fv(p[19].pt); 
  485.   else glTexCoord2f(1, 0);
  486.   glNormal3f(0, 1, 0);
  487.   glVertex3fv(p[19].pt);
  488.   if (flat) glTexCoord2fv(p[20].pt); 
  489.   else glTexCoord2f(.5, 1);
  490.   glNormal3f(0, 0, -1);
  491.   glVertex3fv(p[20].pt);
  492.  
  493.   if (flat) glTexCoord2fv(p[21].pt); 
  494.   else glTexCoord2f(0, 0);
  495.   glNormal3f(0, 0, -1);
  496.   glVertex3fv(p[21].pt);
  497.   if (flat) glTexCoord2fv(p[22].pt); 
  498.   else glTexCoord2f(1, 0);
  499.   glNormal3f(0, -1, 0);
  500.   glVertex3fv(p[22].pt);
  501.   if (flat) glTexCoord2fv(p[23].pt); 
  502.   else glTexCoord2f(.5, 1);
  503.   glNormal3f(-1, 0, 0);
  504.   glVertex3fv(p[23].pt);
  505.  
  506.   glEnd();
  507. }
  508.  
  509. void Stone::draw_shadow(Point dlight) 
  510. {
  511.   Point p[24];
  512.   int i;
  513.  
  514.   transform_points();
  515.   for (i = 0; i < 24; i++) {
  516.     p[i] = points[i];
  517.     if (p[i].pt[2] < 0.0) p[i].pt[2] = 0.0;
  518.     p[i] = p[i].project_direction(dlight);
  519.   }
  520.   draw_faces(p, 1);
  521.   draw_edges(p, 1);
  522.   draw_corners(p, 1);
  523. }
  524.  
  525. void Stone::draw_shadow(Point dlight, GLfloat blur, 
  526.             Color color, Color diffuse)
  527. {
  528.   float b = 1.0 + blur;
  529.   float c, s;
  530.   Point p[8], pp[8];
  531.   Point d, n;
  532.   Color colorp, diffusep;
  533.   int draw[6];
  534.   int i;
  535.  
  536.   if (blur == 0.0) {
  537.     draw_shadow(dlight);
  538.     return;
  539.   }
  540.  
  541.   colorp = color;
  542.   color.c[3] = 1;
  543.   colorp.c[3] = 0;
  544.   diffusep = diffuse;
  545.   diffuse.c[3] = 1;
  546.   diffusep.c[3] = 0;
  547.  
  548.   /* We're being slightly cowardly here and ignoring the erosion - it
  549.    * shouldn't make a big difference */
  550.   p[0].set(-1, -1, -1);
  551.   pp[0] = p[0];
  552.   p[1].set(1, -1, -1);
  553.   pp[1] = p[1];
  554.   p[2].set(1, 1, -1);
  555.   pp[2] = p[2];
  556.   p[3].set(-1, 1, -1);
  557.   pp[3] = p[3];
  558.   p[4].set(-1, -1, 1);
  559.   pp[4] = p[4];
  560.   p[5].set(1, -1, 1);
  561.   pp[5] = p[5];
  562.   p[6].set(1, 1, 1);
  563.   pp[6] = p[6];
  564.   p[7].set(-1, 1, 1);
  565.   pp[7] = p[7];
  566.  
  567.   c = cos(radians(rotation));
  568.   s = sin(radians(rotation));
  569.   for (i = 0; i < 8; i++) {
  570.     p[i] = transform_point(p[i], c, s);
  571.  
  572.     /* This is a complete and utter hack - the net effect is that
  573.      * points which are higher are displaced further when the penumbra 
  574.      * is drawn */
  575.     d = dimensions;
  576.     d.pt[0] += blur * (pp[i].pt[2] + translation.pt[2]);
  577.     d.pt[1] += blur * (pp[i].pt[2] + translation.pt[2]);
  578.     d.pt[2] += blur * (pp[i].pt[2] + translation.pt[2]);
  579.     pp[i] = pp[i].scale(d);
  580.     pp[i] = trans_rot_point(pp[i], c, s);
  581.     if (p[i].pt[2] < 0.0) p[i].pt[2] = 0.0;
  582.  
  583.     p[i] = p[i].project_direction(dlight);
  584.     if (pp[i].pt[2] < 0.0) pp[i].pt[2] = 0.0;
  585.     pp[i] = pp[i].project_direction(dlight);
  586.   }
  587.  
  588.   /* Compute whether or not we should draw various parts of the shadow
  589.    * based upon the normal direction */
  590.   if (dlight.pt[2] > 0.0) dlight *= -1.0;
  591.   n.set(0, 0, -1);
  592.   n = n.rotate_aboutz(c, s);
  593.   draw[0] = (dlight.dot(n) < 0.0);
  594.   n.set(0, -1, 0);
  595.   n = n.rotate_aboutz(c, s);
  596.   draw[1] = (dlight.dot(n) < 0.0);
  597.   n.set(1, 0, 0);
  598.   n = n.rotate_aboutz(c, s);
  599.   draw[2] = (dlight.dot(n) < 0.0);
  600.   n.set(0, 1, 0);
  601.   n = n.rotate_aboutz(c, s);
  602.   draw[3] = (dlight.dot(n) < 0.0);
  603.   n.set(-1, 0, 0);
  604.   n = n.rotate_aboutz(c, s);
  605.   draw[4] = (dlight.dot(n) < 0.0);
  606.   n.set(0, 0, 1);
  607.   n = n.rotate_aboutz(c, s);
  608.   draw[5] = (dlight.dot(n) < 0.0);
  609.  
  610.   /* This part draws the "real" shadow */
  611.   glColor4fv(color.c);
  612.   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  613.  
  614.   glBegin(GL_QUADS);
  615.  
  616.   if (draw[0]) {
  617.     glVertex2fv(p[0].pt);
  618.     glVertex2fv(p[1].pt);
  619.     glVertex2fv(p[2].pt);
  620.     glVertex2fv(p[3].pt);
  621.   }
  622.  
  623.   if (draw[1]) {
  624.     glVertex2fv(p[0].pt);
  625.     glVertex2fv(p[1].pt);
  626.     glVertex2fv(p[5].pt);
  627.     glVertex2fv(p[4].pt);
  628.   }
  629.  
  630.   if (draw[2]) {
  631.     glVertex2fv(p[1].pt);
  632.     glVertex2fv(p[2].pt);
  633.     glVertex2fv(p[6].pt);
  634.     glVertex2fv(p[5].pt);
  635.   }
  636.  
  637.   if (draw[3]) {
  638.     glVertex2fv(p[2].pt);
  639.     glVertex2fv(p[3].pt);
  640.     glVertex2fv(p[7].pt);
  641.     glVertex2fv(p[6].pt);
  642.   }
  643.  
  644.   if (draw[4]) {
  645.     glVertex2fv(p[3].pt);
  646.     glVertex2fv(p[0].pt);
  647.     glVertex2fv(p[4].pt);
  648.     glVertex2fv(p[7].pt);
  649.   }
  650.  
  651.   if (draw[5]) {
  652.     glVertex2fv(p[4].pt);
  653.     glVertex2fv(p[5].pt);
  654.     glVertex2fv(p[6].pt);
  655.     glVertex2fv(p[7].pt);
  656.   }
  657.  
  658.   glEnd();
  659.  
  660.   /* This part draws the penumbra */
  661.  
  662.   glEnable(GL_BLEND);
  663.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  664.  
  665.   glBegin(GL_QUADS);
  666.  
  667.   /* Top */
  668.   if (draw[5]) {
  669.     if (!draw[4]) {
  670.       glColor4fv(color.c);
  671.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  672.       glVertex2fv(p[4].pt);
  673.       glVertex2fv(p[5].pt);
  674.       glColor4fv(colorp.c);
  675.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  676.       glVertex2fv(pp[5].pt);
  677.       glVertex2fv(pp[4].pt);
  678.     }
  679.  
  680.     if (!draw[2]) {
  681.       glColor4fv(color.c);
  682.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  683.       glVertex2fv(p[5].pt);
  684.       glVertex2fv(p[6].pt);
  685.       glColor4fv(colorp.c);
  686.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  687.       glVertex2fv(pp[6].pt);
  688.       glVertex2fv(pp[5].pt);
  689.     }
  690.  
  691.     if (!draw[3]) {
  692.       glColor4fv(color.c);
  693.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  694.       glVertex2fv(p[6].pt);
  695.       glVertex2fv(p[7].pt);
  696.       glColor4fv(colorp.c);
  697.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  698.       glVertex2fv(pp[7].pt);
  699.       glVertex2fv(pp[6].pt);
  700.     }
  701.  
  702.     if (!draw[4]) {
  703.       glColor4fv(color.c);
  704.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  705.       glVertex2fv(p[7].pt);
  706.       glVertex2fv(p[4].pt);
  707.       glColor4fv(colorp.c);
  708.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  709.       glVertex2fv(pp[4].pt);
  710.       glVertex2fv(pp[7].pt);
  711.     }
  712.   }
  713.   /* End of Top */
  714.  
  715.   /* Sides */
  716.   if ((draw[1] || draw[4]) && !(draw[1] && draw[4])) {
  717.     glColor4fv(color.c);
  718.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  719.     glVertex2fv(p[0].pt);
  720.     glVertex2fv(p[4].pt);
  721.     glColor4fv(colorp.c);
  722.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  723.     glVertex2fv(pp[4].pt);
  724.     glVertex2fv(pp[0].pt);
  725.   }
  726.  
  727.   if ((draw[1] || draw[2]) && !(draw[1] && draw[2])) {
  728.     glColor4fv(color.c);
  729.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  730.     glVertex2fv(p[1].pt);
  731.     glVertex2fv(p[5].pt);
  732.     glColor4fv(colorp.c);
  733.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  734.     glVertex2fv(pp[5].pt);
  735.     glVertex2fv(pp[1].pt);
  736.   }
  737.  
  738.   if ((draw[3] || draw[2]) && !(draw[3] && draw[2])) {
  739.     glColor4fv(color.c);
  740.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  741.     glVertex2fv(p[2].pt);
  742.     glVertex2fv(p[6].pt);
  743.     glColor4fv(colorp.c);
  744.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  745.     glVertex2fv(pp[6].pt);
  746.     glVertex2fv(pp[2].pt);
  747.   }
  748.  
  749.   if ((draw[3] || draw[4]) && !(draw[3] && draw[4])) {
  750.     glColor4fv(color.c);
  751.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  752.     glVertex2fv(p[3].pt);
  753.     glVertex2fv(p[7].pt);
  754.     glColor4fv(colorp.c);
  755.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  756.     glVertex2fv(pp[7].pt);
  757.     glVertex2fv(pp[3].pt);
  758.   }
  759.   /* End of Sides */
  760.  
  761.   /* Bottom */
  762.   if (draw[0]) {
  763.     if (!draw[1]) {
  764.       glColor4fv(color.c);
  765.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  766.       glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, diffuse.c);
  767.       glVertex2fv(p[0].pt);
  768.       glVertex2fv(p[1].pt);
  769.       glColor4fv(colorp.c);
  770.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  771.       glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, diffusep.c);
  772.       glVertex2fv(pp[1].pt);
  773.       glVertex2fv(pp[0].pt);
  774.     }
  775.     
  776.     if (!draw[2]) {
  777.       glColor4fv(color.c);
  778.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  779.       glVertex2fv(p[1].pt);
  780.       glVertex2fv(p[2].pt);
  781.       glColor4fv(colorp.c);
  782.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  783.       glVertex2fv(pp[2].pt);
  784.       glVertex2fv(pp[1].pt);
  785.     }
  786.  
  787.     if (!draw[3]) {
  788.       glColor4fv(color.c);
  789.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  790.       glVertex2fv(p[2].pt);
  791.       glVertex2fv(p[3].pt);
  792.       glColor4fv(colorp.c);
  793.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  794.       glVertex2fv(pp[3].pt);
  795.       glVertex2fv(pp[2].pt);
  796.     }
  797.     
  798.     if (!draw[4]) {
  799.       glColor4fv(color.c);
  800.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  801.       glVertex2fv(p[3].pt);
  802.       glVertex2fv(p[0].pt);
  803.       glColor4fv(colorp.c);
  804.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  805.       glVertex2fv(pp[0].pt);
  806.       glVertex2fv(pp[3].pt);
  807.     }
  808.   }
  809.   /* End of Bottom */
  810.  
  811.   glEnd();
  812.  
  813.   glDisable(GL_BLEND);
  814.  
  815. }
  816.  
  817.